import com.pbking.util.eventHandling.*;
/**
 * This class was created to enhance the abilities of the EventDispatcher provided by Macromedia.<BR>
 * It has the same functions (including the ability to "Initialize" a class with Event functions.<BR><BR>
 * 
 * When an event is dispatched, an Event object must be created and used.  Common use is to extend the Event object for specific uses. <BR>
 * This event will be sent to the callback method from the addEventListener or addSingleEventListener methods.<BR><BR>
 * 
 * To initialize a class with the EventBroadcaster methods, that class MUST implement the IEventBroadcaster Interface.<BR>
 * These methods should be empty methods, but should still fulfill the requirements of the interface.<BR>
 * This is to enforce strong typing in the code. 
 * 
 * @author Jason Crist
 */
class com.pbking.util.eventHandling.EventBroadcaster implements IEventBroadcaster {
	
	private var __eventObjects__:Array;
	
	// CONSTRUCTION //////////
	
	function EventDispatcher(){
		//nothing here
	}
	
	/**
	 * Usefull function for a class that cannot extend the EventBroadcaster class yet needs the EventBroadcaster methods.
	 * Simple implement the IEventBroadcaster interface but do not populate the methods with any code. 
	 */
	public static function initialize(target:IEventBroadcaster){
		var tempDispatcher:EventBroadcaster = new EventBroadcaster();
		target.addEventListener = tempDispatcher.addEventListener;
		target.addSingleEventListener = tempDispatcher.addSingleEventListener;
		target.removeEventListener = tempDispatcher.removeEventListener;
		target.removeAllEventTypes = tempDispatcher.removeAllEventTypes;
		target.removeAllEventTargets = tempDispatcher.removeAllEventTargets;
		target.removeAllEvents = tempDispatcher.removeAllEvents;
		target.dispatch = tempDispatcher.dispatch;
	}
	
	public static function initializeMovieClip(target:MovieClip){
		var tempDispatcher:EventBroadcaster = new EventBroadcaster();
		target.addEventListener = tempDispatcher.addEventListener;
		target.addSingleEventListener = tempDispatcher.addSingleEventListener;
		target.removeEventListener = tempDispatcher.removeEventListener;
		target.removeAllEventTypes = tempDispatcher.removeAllEventTypes;
		target.removeAllEventTargets = tempDispatcher.removeAllEventTargets;
		target.removeAllEvents = tempDispatcher.removeAllEvents;
		target.dispatch = tempDispatcher.dispatch;
	}
	
	// PUBLIC FUNCTIONS //////////
	
	/**
	 * Adds an event listener to the target.<BR>
	 * You must supply the type of Event that will be listened for.  Some event names are static vars of the Event class.<BR>
	 * You must supply the target object that the callback will be executed on, and the callback function (usually a function of the target)<BR>
	 * Optionally, you can specify that the event be triggered only once (singleEvent = true).  Usually you would use the addSingleEventListener method for that though.
	 */
	public function addEventListener(eventType:String, target:Object, callback:Function, singleEvent:Boolean){
		if(singleEvent == null) 
			singleEvent = false;
		if(this.__eventObjects__ == null) 
			this.__eventObjects__ = new Array();
		this.__eventObjects__.push(new EventListenerObject(eventType, target, callback, singleEvent));
	}
	
	/**
	 * Same as addSingleEventListener except that singleEvent is always set to true.
	 */
	public function addSingleEventListener(eventType:String, target:Object, callback:Function){
		addEventListener(eventType, target, callback, true);
	}
	
	/**
	 * Remove all event listeners that matches the provided attributes.
	 */
	public function removeEventListener(eventType:String, target:Object, callback:Function){
		for(var i:Number=0; i<__eventObjects__.length; i++){
			var elo:EventListenerObject = this.__eventObjects__[i];
			if(elo.eventType == eventType && elo.target == target && elo.callback == callback){
				__eventObjects__.splice(i,1);
				i--;
			}
		}
	}
	
	/**
	 * Remove all event listeners that match the provided eventType
	 */
	public function removeAllEventTypes(eventType:String){
		for(var i:Number=0; i<__eventObjects__.length; i++){
			var elo:EventListenerObject = this.__eventObjects__[i];
			if(elo.eventType == eventType){
				__eventObjects__.splice(i,1);
				i--;
			}
		}
	}
	
	/**
	 * Remove all event listeners for the provided target.  Usefull when destroying an object that will still have a reference in the event listener.
	 */
	public function removeAllEventTargets(target:Object){
		for(var i:Number=0; i<__eventObjects__.length; i++){
			var elo:EventListenerObject = this.__eventObjects__[i];
			if(elo.target == target){
				__eventObjects__.splice(i,1);
				i--;
			}
		}
	}
	
	/**
	 * Remove ALL event listeners.
	 */
	public function removeAllEvents(){
		this.__eventObjects__ = new Array();
	}
	
	/**
	 * Dispatch an event.  All listeners listening for an eventType that matches the event.eventType will be triggered.  Single event listeners will execute and be removed.<BR>
	 * This method can be triggered externally to "Proxy" an event from an event dispatcher.
	 */
	public function dispatch(event:Event){
		for(var i:Number=0; i<__eventObjects__.length; i++){
			var elo:EventListenerObject = this.__eventObjects__[i];
			if(elo.eventType == event.eventType){
				elo.execute(event);
				if(elo.singleEvent){
					__eventObjects__.splice(i,1);
					i--;
				}
			}
		}
	}
	
}